/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "解算器.h"

#include "节点/插座/C_数值插座.h"
#include "节点/插座/C_矢量插座.h"
#include "节点/插座/C_物理物体插座.h"
#include "节点/插座/通用插座.h"
#include "节点/输入输出节点.h"
#include "node后端.h"

#include <节点/插座/list/list数值插座.h>
#include <节点/插座/list/list物体插座.h>
#include <节点/插座/list/list物理物体插座.h>
#include <节点/插座/list/list矢量插座.h>


#include <节点/节点树.h>
#include <Range.h>


#include <面/几何模型生成.h>
//#include <物理/物理.h>
#include <Context/当前默认操作数据.h>
#include <Context/数据创建销毁.h>
#include <Context/节点数据操作.h>

#include "异步解算/物理异步解算.h"

#include <场景/场景.h>
#include <场景/intern/S_Scene.h>

#define DEF_物理计算帧未初始化 -1



static S_线基本光照材质*	g_域边框材质 = 0;
static S_物体*				g_域大小可视物体 = nullptr;
static S_物体*				g_体素可视物体 = nullptr;



static S_物体* f_域范围可视物体(S_设备环境& ctx) {
	if (!g_域边框材质) {
		g_域边框材质 = new S_线基本光照材质(ctx);
	}


	if (g_域大小可视物体 == nullptr) {
		g_域大小可视物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);
		f_ob_set数据槽数量(g_域大小可视物体, 1);

		auto* mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan);
		g_域大小可视物体->f_setData(mesh, 0);

		f_ob_set材质(g_域大小可视物体, g_域边框材质, 0);



		DEF_3Fs 顶点;
		DEF_3Fs 法线;
		DEF_2Fs UV;
		DEF_Is 索引;
		
		f_graph_构建立方体({ 1,1,1 }, { 1,1,1 }, 顶点, 法线, UV, 索引);


		std::vector<S_VN> vnData;
		f_surface_数组合并(vnData, 顶点, 法线);
		f_mesh_fill顶点数据(mesh, vnData);
		f_填充索引数据(mesh, 索引);

		g_域大小可视物体->m_Name = u"域范围可视物体";
	}

	return g_域大小可视物体;
}







C_FLIP解算器节点::C_FLIP解算器节点(E_物理引擎 解算器类型, S_设备环境& ctx) : C_节点基类("FLIP解算器节点") {
	f_setWName(u"FLIP");
	m_GPU环境 = ctx;
	m_解算器类型 = 解算器类型;
	C_插座基类* socket;
	
	DEF_创建UI32插座_I(u"域分辨率");
	DEF_创建F32插座_v1_I(u"域边界大小");
	DEF_创建F32插座_v1_I(u"步进时间");

	DEF_创建物理引擎插座_O(u"物理引擎");


	DEF_UI32插座数据(f_get输入插座(1), 0) = 32;
	DEF_F32插座数据(f_get输入插座(2)) = 1.0f;
	DEF_F32插座数据(f_get输入插座(3)) = 1.0f / 60.0f;


	f_域范围可视物体(ctx);
}

C_FLIP解算器节点::~C_FLIP解算器节点() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1), 0);

	if (m_Physics) {
		f_phy_销毁物理解算器(m_Physics);
	}

	f_get输出插座(1)->f_setData((S_Physics*)nullptr, 0);
}

bool C_FLIP解算器节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1), 0);
	S_Mesh* mesh = 0;

	if (!m_Physics) {
		m_Physics = f_phy_创建创建解算器(m_解算器类型, { 10, 10 , 10 });
		f_get输出插座(1)->f_setData(m_Physics, 0);
		f_NodeCtx_get默认场景()->f_add物体({ g_域大小可视物体 }, E_场景物体容器类型::e_集合);
	}

	uint32 域分辨率 = DEF_UI32插座数据(f_get输入插座(1), 0);
	float32 域大小 = DEF_F32插座数据(f_get输入插座(2));

	if (域分辨率 <= 0) 域分辨率 = 1;
	if (域分辨率 > 512) 域分辨率 = 512;


	S_域区& dom = *f_Phy_get域属性(m_Physics);
	if (dom.m_单元属性.m_分辨率.x != 域分辨率) {
		dom.m_单元属性.m_分辨率.x = 域分辨率;
		dom.m_单元属性.m_分辨率.y = 域分辨率;
		dom.m_单元属性.m_分辨率.z = 域分辨率;


		g_域大小可视物体->f_set缩放(dom.m_单元属性.m_分辨率.x, dom.m_单元属性.m_分辨率.y, dom.m_单元属性.m_分辨率.z);
	}


	dom.m_单元属性.m_世界大小.x = 域大小;
	dom.m_单元属性.m_世界大小.y = 域大小;
	dom.m_单元属性.m_世界大小.z = 域大小;


	const uint32 old分辨率 = f_phy_get解算器域分辨率(m_Physics);
	if (old分辨率 != 域分辨率) {
		
		f_Phy_set解算器域分辨率(m_Physics, m_解算器类型, 域分辨率, { 域大小 ,域大小, 域大小}, 0.1);
		
	}
	else {
		//mesh = f_ob_from物体Mesh(m_数据可视物体);
	}



	/*if (域分辨率) {
		E_序列map v = mesh->f_map顶点();

		//填充GPU可视数据
		f_Phy_取流体调试数据(m_Physics, (S_FLIP可视数据*)v.point);

		mesh->f_unmap顶点();
	}*/
	return false;
}



void C_FLIP解算器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_FLIP解算器节点::f_写入(FILE* f) {
	
	C_节点基类::f_写入(f);
}


C_节点基类* f_node_加载FLIP解算器节点(S_设备环境& ctx, FILE* f) {
	E_物理引擎 解算器类型;
	fread(&解算器类型, sizeof(uint32), 1, f);

	C_FLIP解算器节点* node = new C_FLIP解算器节点(解算器类型, ctx);
	return node;
}

void f_node_保存FLIP解算器节点(C_节点基类* n, FILE* f) {
	C_FLIP解算器节点* node = dynamic_cast<C_FLIP解算器节点*>(n);

	fwrite(&node->m_解算器类型, sizeof(uint32), 1, f);

}











void fp_解算器切换(S_Props& prop) {

}

C_PBF解算器节点::C_PBF解算器节点(S_设备环境& ctx) : C_节点基类("PBF解算器节点") {
	f_setWName(u"PBF");
	//m_GPU环境 = ctx;
	m_解算器类型 = E_物理引擎::E_物理引擎_PBF;
	m_记录物理体状态 = DEF_物理计算帧未初始化;

	C_插座基类* socket;
	DEF_创建F32插座_v1_I(u"步进时间");
	DEF_创建F32插座_v1_I(u"解算精度");
	//DEF_创建F32插座_I(u"碰撞单元大小");
	DEF_创建物理体_1D插座_I(u"物理体");
	DEF_创建物理引擎插座_O(u"物理引擎");
	f_域范围可视物体(ctx);
	DEF_F32插座数据(f_get输入插座(1)) = 1.0f/60.0f;
	m_物理引擎类型 = f_alloc_EnumProp(nullptr, { {u"FleX", u""}, {u"内部", u""}, {u"SPlisHSPlasH", u""} }, u"解算器", 0, fp_解算器切换);
	m_物理引擎类型.m_私有 = true;
	m_GPU = f_alloc_EnumProp(nullptr, { {u"GPU:0", u""}, {u"GPU:1", u""}, {u"GPU:2", u""} }, u"GPU ID", 0, fp_解算器切换);
	m_GPU.m_私有 = true;
	m_飞溅粒子数量 = f_alloc_UI32Prop(nullptr, u"飞溅粒子数量", 1000);
	m_飞溅粒子数量.m_私有 = true;
	
}
C_PBF解算器节点::~C_PBF解算器节点() {
	f_release_EnumProp(m_物理引擎类型);
}
bool C_PBF解算器节点::f_update() {
	float32 r = DEF_F32插座数据(f_get输入插座(2));
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	S_Mesh* mesh = 0;
	auto& phytype = f_prop_enum(m_物理引擎类型);
	if (!m_Physics) {
		switch (phytype) {
			case 0:
				break;
			case 1:
				m_Physics = f_phy_创建创建解算器(m_解算器类型, { 10, 10 , 10 });
				m_Physics->m_IdType = E_物理引擎::E_物理引擎_PBF;
				break;
			case 2:
				break;
		}
		m_Physics->m_Key = m_记录物理体状态;
		f_get输出插座(1)->f_setData(m_Physics, 0);
	}
	switch (phytype) {
		case 0: {
			uint32 LinkNum = f_get输入插座(3)->f_getLinkNum();
			uint32 构建ID = 0;
			uint64 offset = 0;

			break;
		}
		case 1: {
		
			break;
		}
		case 2:
			break;
	}

	return false;
}


void C_PBF解算器节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_物理引擎类型, f);
	f_prop_Load(m_GPU, f);
	f_prop_Load(m_飞溅粒子数量, f);
	fread(&m_记录物理体状态, sizeof(uint64), 1, f);
}
void C_PBF解算器节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_物理引擎类型, f);
	f_prop_Save(m_GPU, f);
	f_prop_Save(m_飞溅粒子数量, f);
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	if (m_Physics) {
		fwrite(&m_Physics->m_Key, sizeof(uint64), 1, f);
	}
	else {
		fwrite(&m_记录物理体状态, sizeof(uint64), 1, f);
	}
}
C_节点基类* f_node_加载PBF解算器节点(S_设备环境& ctx, FILE* f) {
	C_PBF解算器节点* node = new C_PBF解算器节点(ctx);
	auto& phytype = f_prop_enum(node->m_物理引擎类型);
	uint32 解算器类型;
	fread(&解算器类型, sizeof(uint32), 1, f);
	phytype = 解算器类型;
	return node;
}
void f_node_保存PBF解算器节点(C_节点基类* n, FILE* f) {
	C_PBF解算器节点* node = dynamic_cast<C_PBF解算器节点*>(n);
	auto& phytype = f_prop_enum(node->m_物理引擎类型);
	uint32 解算器类型 = f_prop_enum(node->m_物理引擎类型);
	fwrite(&解算器类型, sizeof(uint32), 1, f);
}





static void f_清除缓存标记(void* ops) {
	auto& node = *((C_物理引擎节点*)ops);

	S_Physics* m_Physics = DEF_物理引擎插座数据(node.f_get输出插座(1), 0);

	auto 帧标记路径 = f_NE_get物理缓存路径(m_Physics, S_节点数据::g流体缓存帧ID, m_Physics->m_缓存区间, 0, false);
	if (f_phy_清除模拟帧标记(m_Physics, 0,0, 帧标记路径)) {
		node.f_set是否要更新(true);
	}
}

C_物理引擎节点::C_物理引擎节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_物理引擎节点, E_节点类型::e_节点Type_解算) {
	f_setWName(u"物理引擎");
	m_Ctx = ctx;
	m_记录物理体状态 = DEF_物理计算帧未初始化;

	DEF_创建物理体_1D插座_I(u"物理体");
	DEF_创建物理引擎插座_O(u"物理引擎");

	f_get输入插座(1)->f_set多输入();



	m_物理引擎类型 = f_创建物理引擎类型属性数据();
	m_物理引擎类型.m_私有 = true;
	f_prop_enum(m_物理引擎类型) = 3;


	m_模型读写路径 = f_alloc_PathProp(nullptr, u"模型读写路径");
	m_模型读写路径.m_私有 = true;

	m_GPU = f_alloc_EnumProp(nullptr, {
		{u"CPU"},
		{u"GPU"},
	}, u"计算设备");
	m_GPU.m_私有 = true;
	//f_prop_Path(m_模型读写路径) = S_引擎配置::g_程序路径 + "Mujoco.xml";
	//f_prop_LineStr(m_模型读写路径) = S_引擎配置::g_程序路径 + "Mujoco.xml";
	f_prop_Path(m_模型读写路径) = S_引擎配置::g_工程文件临时路径 + f_getWName() + u".xml";


	if (link_tree) {
		C_节点基类::f_绑定子集节点树(link_tree);
	}
	else {
		auto* 子树 = f_node_Create物理节点树(false, u"phy_");
		C_节点基类::f_绑定子集节点树(子树);

		auto 输入组节点 = new C_输入组节点(ctx);
		auto 输出组节点 = new C_输出组节点(ctx);
		f_node_节点树添加节点(子树, 输入组节点);
		f_node_节点树添加节点(子树, 输出组节点);
	}
	
	m_自定义更新方式 = true;
	f_绑定this节点树(m_当前节点所在节点树);
	m_动画曲线列表 = f_an_创建曲线层();


	m_域可视物体 = f_ob_创建(E_物体类型::t_虚拟体);
	m_域可视物体->m_视口显示模式 = E_物体视口显示::e_OVS_轮廓 | E_物体视口显示::e_OVS_面;
	m_域可视物体->m_视口显示模式 |= m_域可视物体->m_视口显示模式 << 16;
	m_域可视物体->m_Name = u"物理域";
	f_ob_set附属类型(m_域可视物体, E_物体类型::t_包围盒);

	auto m1 = f_surface_创建实例(S_节点数据::g_me_立方体);
	auto m2 = f_surface_创建实例(S_节点数据::g_me_边界框);
	m1->m_Color = { 10,10,10,255 };
	m2->m_Color = { 10,200,100,255 };
	m_域可视物体->m_颜色 = { 10,210,10,255 };

	f_ob_set数据槽数量(m_域可视物体, 2);
	f_ob_set数据(m_域可视物体, m1, 0);
	f_ob_set数据(m_域可视物体, m2, 1);

	f_mesh_set绘制内存属性(m1, {});
	f_mesh_set绘制内存属性(m2, {});
	f_ob_set颜色2(m_域可视物体, m1->m_Color, m_域可视物体->m_实例ID, 0);
	f_ob_set颜色2(m_域可视物体, m2->m_Color, m_域可视物体->m_实例ID, 1);

	f_ob_set材质(m_域可视物体, f_NodeCtx_get基本光照线段材质(), 0);
	f_ob_set材质(m_域可视物体, f_NodeCtx_get基本光照线段材质(), 1);
	f_ob_set线宽(m_域可视物体, 0.8, 0);
	f_ob_set线宽(m_域可视物体, 2.5, 1);

	f_node_物体添加到主场景(m_域可视物体);
	f_node_物体添加到全局容器(m_域可视物体);

	f_NodeCtx_录物体类节点(this, m_域可视物体);
	


	m_域大小 = f_alloc_Vec3Prop(&m_域可视物体->m_变换.scale, u"域大小");
	m_域大小.m_私有 = true;

	m_单元大小 = f_alloc_F32Prop(nullptr, u"网格大小");
	m_单元大小.m_私有 = true;

	m_开启飞溅粒子 = f_alloc_BoolProp(nullptr, u"开启飞溅粒子");
	m_开启飞溅粒子.m_私有 = true;

	m_飞溅粒子数量 = f_alloc_UI32Prop(nullptr, u"飞溅粒子数量", 0);
	m_飞溅粒子数量.m_私有 = true;
	

	m_清除所有缓存 = f_alloc_对象回调Prop(f_清除缓存标记, this, u"清除缓存");
	m_清除所有缓存.m_私有 = true;



	f_prop_Vec3(m_域大小) = { 10,10,10 };
	f_prop_F32(m_单元大小) = 0.2;

	f_prop_Bool(m_开启飞溅粒子) = false;
}

C_物理引擎节点::~C_物理引擎节点() {
	f_prop_Release(m_物理引擎类型);
	f_prop_Release(m_模型读写路径);
	f_prop_Release(m_GPU);

	f_prop_Release(m_域大小);
	f_prop_Release(m_单元大小);

	f_prop_Release(m_清除所有缓存);


	S_Physics* physics = DEF_物理引擎插座数据(f_get输出插座(1));
	S_节点数据::g_物理引擎.erase(physics);

}

bool C_物理引擎节点::f_update() {
	if (m_子集节点树->m_节点结构改变) {
		m_InNodes.clear();
		m_OutNudes.clear();
		f_get子集输入节点(m_InNodes);
		f_get子集输出节点(m_OutNudes);
	}


	uint32 num = f_get输入插座数量();
	
	f_NT_StepUpdate节点(m_子集节点树, true);
	f_NodeCtx_节点模拟入栈(this, false);

	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	if (m_Physics) {
		if (m_Physics->m_IdType != f_prop_enum(m_物理引擎类型)) {
			f_phy_销毁物理解算器(m_Physics);
			goto To_物理引擎创建;
		}
	}
	else {
	To_物理引擎创建:
		m_Physics = f_phy_创建创建解算器(E_物理引擎(f_prop_enum(m_物理引擎类型)), {}, &m_Ctx);
		S_节点数据::g_物理引擎.insert(m_Physics);

		f_get输出插座(1)->f_setData(m_Physics);
	}

	f_prop_Path(m_模型读写路径) = S_引擎配置::g_工程文件路径 + f_getWName() + u".xml";
	auto path = f_prop_Path(m_模型读写路径).string();
	f_phy_重构(m_Physics, path);
	m_Physics->m_是否初始化 = true;

	f_phy_set解算器域(m_Physics, f_prop_Vec3(m_域大小), m_域可视物体->m_变换.position, f_prop_F32(m_单元大小));

	f_phy_set飞溅粒子(m_Physics, f_prop_Bool(m_开启飞溅粒子), f_prop_UI32(m_飞溅粒子数量));


	f_get输出插座(1)->f_setData(m_Physics);
	return false;
}

void C_物理引擎节点::f_异步解算() {
	auto* socket1 = f_get输入插座(1);
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输出插座(1));
	f_phy_重构(m_Physics, "");


	std::vector<S_物理体*> 物理体;
	uint32 body_num = socket1->f_getLinkNum();

	S_PhyBodyArray* ma = (S_PhyBodyArray*)f_core_array_new_type(0, E_值类型::e_插座Type_物理体_Array1D);
	for (uint32 i = 0; i < body_num; ++i) {
		auto* bodys = (S_PhyBodyArray*)(socket1->f_getData(i));

		f_core_array_append((S_Array*)ma, (S_Array*)bodys);
	}
	f_phy_添加物理体(m_Physics, ma);
}

void C_物理引擎节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_8, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_物理引擎类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_模型读写路径, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_GPU, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_域大小, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_单元大小, 下一次读取数据指针);

			//下一次读取数据指针 = f_ob_Load物体(m_域可视物体, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_物理引擎节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_物理引擎类型, 块);
	f_prop_Save(m_模型读写路径, 块);
	f_prop_Save(m_GPU, 块);

	f_prop_Save(m_域大小, 块);
	f_prop_Save(m_单元大小, 块);

	//f_ob_Save物体(m_域可视物体, 块);

	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_物理引擎节点::f_虚拟体() {
	return m_域可视物体;
}

void C_物理引擎节点::f_删除() {
	m_域可视物体->m_显示 = false;
	f_node_物体从主场景中移除(m_域可视物体);
	f_node_从全局容器移除物体(m_域可视物体);

	S_Physics* physics = DEF_物理引擎插座数据(f_get输出插座(1));
	S_节点数据::g_物理引擎.erase(physics);
}

void C_物理引擎节点::f_回收() {
	m_域可视物体->m_显示 = true;
	f_node_物体添加到主场景(m_域可视物体);
	f_node_物体添加到全局容器(m_域可视物体);

	S_Physics* physics = DEF_物理引擎插座数据(f_get输出插座(1));
	S_节点数据::g_物理引擎.insert(physics);
}

C_节点基类* f_node_创建物理引擎节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_物理引擎节点(ctx, 子节点树);
}

C_节点基类* f_node_加载物理引擎节点(S_设备环境& ctx, FILE* f) {
	std::u16string 链接的节点树名称 = f_file_读取字符串(f);

	if (S_节点数据::G用于重新映射节点树到节点的容器.find(链接的节点树名称) == S_节点数据::G用于重新映射节点树到节点的容器.end()) {
		f_node_加载节点树(ctx, f);
	}

	C_物理引擎节点* node = new C_物理引擎节点(ctx, S_节点数据::G用于重新映射节点树到节点的容器[链接的节点树名称]);
	return node;
}

void f_node_保存物理引擎节点(C_节点基类* n, FILE* f) {
	C_物理引擎节点* node = dynamic_cast<C_物理引擎节点*>(n);

	auto* tree = node->f_get子集树();
	f_file_保存字符串(f, tree->m_IDName);

	if (tree->m_未保存或加载) {
		tree->m_未保存或加载 = false;

		std::vector<C_节点树*> trees = { tree };
		f_node_保存节点树(trees, f);
	}
}






C_PBF粒子容器节点::C_PBF粒子容器节点(S_设备环境& ctx) : C_节点基类("PBF粒子容器节点") {

}

C_PBF粒子容器节点::~C_PBF粒子容器节点() {

}

bool C_PBF粒子容器节点::f_update() {
	return false;
}


C_节点基类* f_node_加载PBF粒子容器节点(S_设备环境& ctx, FILE* f) {
	C_PBF粒子容器节点* node = new C_PBF粒子容器节点(ctx);
	return node;
}

void f_node_保存PBF粒子容器节点(C_节点基类* n, FILE* f) {
	C_PBF粒子容器节点* node = dynamic_cast<C_PBF粒子容器节点*>(n);
	//fwrite(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
}

C_节点基类* f_node_加载PBF更新邻接信息节点(S_设备环境& ctx, FILE* f) {
	return nullptr;
}

void f_node_保存PBF更新邻接信息节点(C_节点基类* n, FILE* f) {
	
}






static void f_清除当前帧之后缓存标记(void* ops) {
	auto& node = *((C_解算器更新节点*)ops);
	S_Physics* m_Physics = DEF_物理引擎插座数据(node.f_get输入插座(1), 0);

	f_phy_清除模拟帧标记(m_Physics, node.f_get时间帧());
}

C_解算器更新节点::C_解算器更新节点(S_设备环境& ctx) : C_节点基类("解算器更新节点") {
	f_setWName(u"解算器更新");
	m_Ctx = ctx;
	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
	m_显示域体素 = true;
	m_是否完成计算 = 0;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建F32插座_v1_I(u"时间步进");
	DEF_创建物体_1D插座_I(u"力");
	
	DEF_创建物理引擎插座_O(u"物理引擎");


	float32 步进时间 = 0.0;
	f_get输入插座(2)->f_setData(&步进时间);
	f_get输入插座(3)->f_set多输入();
	//if (gPBF体素可视 == nullptr) {
	//	gPBF体素可视 = new S_体素可视网格预览材质(ctx);
	//}


	m_上一次可视数据分辨率 = 0;
	m_数据可视物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);
	m_飞溅可视物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);
	m_数据可视物体->m_Name = u"物理流体可视物体";
	f_ob_set数据槽数量(m_数据可视物体, 2);
	f_ob_set数据槽数量(m_飞溅可视物体, 1);
	
	

	auto* 粒子 = f_surface_创建网格对象(0, ctx, false, E_网格数据枚举::e_Mesh_Vulkan);
	auto* 体素 = f_surface_创建网格对象(0, ctx, false, E_网格数据枚举::e_Mesh_Vulkan);
	f_ob_set数据(m_数据可视物体, 粒子, 0);
	f_ob_set数据(m_数据可视物体, 体素, 1);
	f_ob_set材质(m_数据可视物体, f_NodeCtx_getFLIP调试预览材质(), 0);
	f_ob_set材质(m_数据可视物体, f_NodeCtx_get包围盒材质(), 1);
	f_ob_set附属类型(m_数据可视物体, E_物体类型::t_包围盒);

	f_mesh_set绘制内存属性(粒子, {});
	f_mesh_set绘制内存属性(体素, {});

	m_数据可视物体->m_可拾取 = false;
	m_飞溅可视物体->m_可拾取 = false;
	f_node_物体添加到主场景(m_数据可视物体);
	f_node_物体添加到全局容器(m_数据可视物体);
	f_NodeCtx_录物体类节点(this);
	m_数据可视物体->m_视口显示模式 = 3 | (3<<16);
	//mesh = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan);
	//m_飞溅可视物体->f_setData(mesh, 0);
	//f_ob_set材质(m_飞溅可视物体, gPBF材质飞溅粒子, 0);
	//
	//m_肌腱可视物体 = f_ob_创建物体(ctx, E_物体类型::t_网格);
	//f_ob_set数据槽数量(m_肌腱可视物体, 1);
	//auto* 肌腱网格 = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan);
	//f_ob_set数据(m_肌腱可视物体, 肌腱网格);
	//f_ob_set材质(m_肌腱可视物体, gPBF材质飞溅粒子, 0);


	//m_粒子是否可视 = f_alloc_BoolProp(&m_数据可视物体->m_渲染, u"粒子可视");
	//m_粒子是否可视.m_私有 = true;

	m_是否多线程 = f_alloc_BoolProp(nullptr, u"多线程");
	m_是否多线程.m_私有 = true;

	m_时间区间 = f_alloc_uVec2Prop(nullptr, u"时间区间");
	m_时间区间.m_私有 = true;
	f_prop_uVec2(m_时间区间) = { 0, 256 };

	m_是否缓存 = f_alloc_BoolProp(nullptr, u"是否缓存", false);
	m_是否缓存.m_私有 = true;

	m_缓存路径 = f_alloc_PathProp(nullptr, u"缓存路径", std::filesystem::temp_directory_path().u16string());
	m_缓存路径.m_私有 = true;

	m_缓存方式 = f_alloc_EnumProp(nullptr, {{u"播放", u""}, {u"模块",u""}, {u"粒子",u""}}, u"缓存方式");
	m_缓存方式.m_私有 = true;

	m_文件名 = f_alloc_LineStrProp(nullptr, u"文件名称", u"PBF缓存");
	m_文件名.m_私有 = true;

	m_缓存压缩 = f_alloc_BoolProp(nullptr, u"缓存压缩", false);
	m_缓存压缩.m_私有 = true;

	m_清除当前帧后缓存 = f_alloc_对象回调Prop(f_清除当前帧之后缓存标记, this, u"清除帧后缓存");
	m_清除当前帧后缓存.m_私有 = true;


	
	m_保留缓存设备 = f_alloc_EnumProp(nullptr, {{u"无"},{u"内存"},{u"显存"}}, u"保留缓存设备");
	m_保留缓存设备.m_私有 = true;

	m_保留缓存数量 = f_alloc_UI32Prop(nullptr, u"保留缓存数量", 10);
	m_保留缓存数量.m_私有 = true;


	m_重置时间 = f_alloc_UI32Prop(nullptr, u"重置时间", 0);
	m_重置时间.m_私有 = true;
	f_prop_UI32(m_重置时间) = 0;

	m_时间步进 = f_alloc_F32Prop(nullptr, u"时间步进", 0);
	m_时间步进.m_私有 = true;
	f_prop_F32(m_时间步进) = 0.016;

	m_子帧 = f_alloc_UI32Prop(nullptr, u"子帧", 0);
	m_子帧.m_私有 = true;
	f_prop_UI32(m_子帧) = 1;

	m_变换物体 = f_alloc_BoolProp(nullptr, u"变换物体");
	m_变换物体.m_私有 = true;
	f_prop_Bool(m_变换物体) = true;


	m_视口互交 = f_alloc_BoolProp(nullptr, u"视口互交");
	m_视口互交.m_私有 = true;
	f_prop_Bool(m_视口互交) = false;


	m_可视项 = f_alloc_FlagBitsEnumProp(nullptr, *S_节点UI数据::g_物理可视项, u"可视项");
	m_可视项.m_私有 = true;
	f_prop_UI32位域枚举(m_可视项);
	//auto t = f_StringToWString(S_引擎配置::g_工程文件临时路径) + m_Name + u".xml";
	//f_prop_Str(m_文件名) = t;
}

C_解算器更新节点::~C_解算器更新节点() {
	f_node_物体从主场景中移除(m_数据可视物体);
	f_NodeCtx_get默认场景()->f_remove物体(m_飞溅可视物体, E_场景物体容器类型::e_集合);
	f_NodeCtx_get默认场景()->f_remove物体(m_肌腱可视物体, E_场景物体容器类型::e_集合);

	f_prop_Release(m_时间区间);

	f_prop_Release(m_是否缓存);
	f_prop_Release(m_缓存路径);
	
	f_prop_Release(m_清除当前帧后缓存);

	f_prop_Release(m_缓存方式);
	f_prop_Release(m_文件名);
	f_prop_Release(m_缓存压缩);

	f_prop_Release(m_保留缓存设备);
	f_prop_Release(m_保留缓存数量);

	f_prop_Release(m_时间步进);
	f_prop_Release(m_子帧);
	f_prop_Release(m_变换物体);
	f_prop_Release(m_可视项);
}

bool C_解算器更新节点::f_update() {
	
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		return m_是否完成计算;
	}
	
	auto& frame = f_NodeCtx_get帧();
	m_Physics->m_步进ID = frame.当前帧;

	ivec2 区间 = f_prop_iVec2(m_时间区间);
	auto 当前帧 = f_get时间帧();
	if (m_Physics->m_是否初始化) {
		auto 帧标记ID文件保存路径 = f_get缓存路径(m_Physics, S_节点数据::g流体缓存帧ID, 0, false);
		f_phy_构建缓存帧标记(m_Physics, (frame.帧区间.y + 1) - max(0, frame.帧区间.x), 帧标记ID文件保存路径);

		m_Physics->m_缓存路径 = f_prop_Path(m_缓存路径);
		m_Physics->m_缓存文件名称 = f_prop_WStr(m_文件名);
		m_Physics->m_缓存区间 = 区间;
	}
	else if (m_Physics->m_参数改变) {
		f_phy_清除模拟帧标记(m_Physics, 当前帧);
	}

	
	if (m_子集节点树->g_节点是否可编辑) {
		m_子集节点树->g_节点是否可编辑;
	}
	f_get输出插座(1)->f_setData(m_Physics);

	float32 帧时间 = DEF_F32插座数据(f_get输入插座(2));
	


	std::vector<S_PBF_force> 力;

	auto* socket3 = f_get输入插座(3);
	uint32 接入数量 = socket3->f_getLinkNum();
	for (uint32 i = 0; i < 接入数量; ++i) {
		auto* 力物体 = (S_OBArray*)socket3->f_getData(i);

		for (uint32 k = 0; k < 力物体->count; ++k) {
			力.push_back(*(S_PBF_force*)力物体->ptr_userData[k]->m_UserData);
		}
	}
	f_phy_添加力(m_Physics, 力);




	switch (f_prop_enum(m_缓存方式)) {
		case E_物理缓存方式::e_phyCache_重播: {
			break;
		}
		case E_物理缓存方式::e_phyCache_模块: {
			break;
		}
		case E_物理缓存方式::e_phyCache_粒子: {
			break;
		}
		default:
			break;
	}
	


	std::string 文件路径[2] = {
		f_get缓存路径(m_Physics, S_节点数据::g流体缓存类型名称, 当前帧, true)
		,f_get缓存路径(m_Physics, S_节点数据::g流体缓存类型名称, 当前帧 - 1, true)
	};
	if (f_phy_读取缓存(m_Physics, 文件路径, E_物理缓存方式(f_prop_enum(m_缓存方式)), 当前帧)) {
		f_粒子可视更新(m_Physics);

		if (f_prop_Bool(m_变换物体)) {
			f_phy_更新粒子绘制缓存(m_Physics, frame.子帧);
		}

		m_Physics->m_是否初始化 = false;
		m_Physics->m_参数改变 = false;

	}
	else {
		if (S_节点数据::g_开启节点帧更新 || m_Physics->m_是否初始化) {
			f_NodeCtx_节点模拟入栈(this, false);
		}
	}


	
	m_是否完成计算 = 0;
	return false;
	
}

void C_解算器更新节点::f_异步解算() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		auto p = f_get输入插座(1)->f_get属性数据(E_值类型::e_插座Type_物理解算器);
		if (p.size()) {
			m_Physics = (S_Physics*)(p[0]);
		}
		return;
	}


	auto& frame = f_NodeCtx_get帧();
	ivec2 区间 = f_prop_iVec2(m_时间区间);
	if (m_Physics->m_步进ID <= 区间.x || m_Physics->m_是否初始化) {
		f_phy_重置运动(m_Physics);
		m_Physics->m_是否初始化 = false;
		
		m_缓存保存帧 = 0;
		m_是否完成计算 = 0;
	}


	

	float32 时间步进 = f_prop_F32(m_时间步进);
	uint32 子帧 = f_prop_UI32(m_子帧);

	for (uint32 i = 0; i < 子帧; ++i) {
		switch (m_Physics->m_IdType) {
			case E_物理引擎::E_物理引擎_MPM:
			case E_物理引擎::E_物理引擎_PBF:
			case E_物理引擎::E_物理引擎_Mujoco: {
				f_phy_步进解算(m_Physics, 时间步进);
				break;
			}

			case E_物理引擎::E_物理引擎_FLIP: {

				break;
			}

			case E_物理引擎::E_物理引擎_Bullet: {
				m_Physics->f_Update();
				break;
			}
		}
	}


	f_粒子可视更新(m_Physics);

	if (f_prop_Bool(m_变换物体)) {
		f_phy_更新粒子绘制缓存(m_Physics, 0);
	}


	if (f_prop_Bool(m_是否缓存)) {
		auto 当前帧 = f_get时间帧();
		auto 文件保存路径 = f_get缓存路径(m_Physics, S_节点数据::g流体缓存类型名称, 当前帧, true);
		f_phy_写入缓存(m_Physics, 文件保存路径, E_物理缓存方式(f_prop_enum(m_缓存方式)));

		文件保存路径 = f_get缓存路径(m_Physics, S_节点数据::g流体缓存帧ID, 0, false);
		f_phy_标记帧缓存(m_Physics, 当前帧, 1, 文件保存路径);
	}


	m_是否完成计算 = 2;
	m_Physics->m_步进时间 += 1.0;
	m_Physics->m_参数改变 = false;
}

void C_解算器更新节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_重置时间, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_是否多线程, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_时间区间, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_子帧, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_是否缓存, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_缓存路径, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_缓存方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件名, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_缓存压缩, 下一次读取数据指针);
			//下一次读取数据指针 = f_prop_Load(m_清除缓存, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_保留缓存设备, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_保留缓存数量, 下一次读取数据指针);

			下一次读取数据指针 = f_prop_Load(m_视口互交, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_可视项, 下一次读取数据指针);

		}

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_21, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_变换物体, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_解算器更新节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_重置时间, 块);
	f_prop_Save(m_是否多线程, 块);
	f_prop_Save(m_时间区间, 块);
	f_prop_Save(m_子帧, 块);

	f_prop_Save(m_是否缓存, 块);
	f_prop_Save(m_缓存路径, 块);
	f_prop_Save(m_缓存方式, 块);
	f_prop_Save(m_文件名, 块);
	f_prop_Save(m_缓存压缩, 块);
	//f_prop_Save(m_清除缓存, 块);

	f_prop_Save(m_保留缓存设备, 块);
	f_prop_Save(m_保留缓存数量, 块);


	f_prop_Save(m_视口互交, 块);
	f_prop_Save(m_可视项, 块);

	f_prop_Save(m_变换物体, 块);

	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_解算器更新节点::f_虚拟体() {
	return nullptr;
}

void C_解算器更新节点::f_删除() {
	m_数据可视物体->m_显示 = false;
	f_node_物体从主场景中移除(m_数据可视物体);
	f_node_从全局容器移除物体(m_数据可视物体);
}

void C_解算器更新节点::f_回收() {
	m_数据可视物体->m_显示 = true;
	f_node_物体添加到主场景(m_数据可视物体);
	f_node_物体添加到全局容器(m_数据可视物体);
}

std::string C_解算器更新节点::f_get缓存路径(S_Physics* Physics, const std::string& type, int32 帧, bool 序列) {
	ivec2 区间 = f_prop_iVec2(m_时间区间);
	
	if (帧 > 区间.y || 帧 < 区间.x) {
		return "";
	}
	std::string 编号 = f_整数值转字符串(帧);
	
	auto path = f_prop_Path(m_缓存路径);
	if(path.empty()) return "";

	auto 文件路径 = path / f_prop_WStr(m_文件名);

	std::string 保存路径 = 文件路径.string();
	if (序列) {
		保存路径 += "_" + 编号;
	}
	保存路径 += type;
	return 保存路径;
}

int32 C_解算器更新节点::f_get时间帧() {
	auto& frame = f_NodeCtx_get帧();
	ivec2 区间 = f_prop_iVec2(m_时间区间);

	return clamp(frame.当前帧, 区间.x, 区间.y);
}

void C_解算器更新节点::f_粒子可视更新(S_Physics* physics) {
	uint32 可视项 = f_prop_UI32位域枚举(m_可视项);
	if (可视项 & 1) {
		f_Phy_取流体调试数据(physics, m_数据可视物体);
		f_ob_getMesh(m_数据可视物体, 0)->m_显示 = true;
	}
	else {
		f_ob_getMesh(m_数据可视物体, 0)->m_显示 = false;
	}

	if (可视项 & 2) {
		f_Phy_取流体调试数据(physics, m_数据可视物体, 1);
		f_ob_getMesh(m_数据可视物体, 1)->m_显示 = true;
	}
	else {
		f_ob_getMesh(m_数据可视物体, 1)->m_显示 = false;
	}
}

C_节点基类* f_node_创建解算器更新节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_解算器更新节点(ctx);
}

C_节点基类* f_node_加载解算器更新节点(S_设备环境& ctx, FILE* f) {
	C_解算器更新节点* node = new C_解算器更新节点(ctx);
	return node;
}

void f_node_保存解算器更新节点(C_节点基类* n, FILE* f) {

}
























C_解算器添加物体节点::C_解算器添加物体节点(S_设备环境& ctx) : C_节点基类("解算器添加物体节点") {
	f_setWName(u"解算器添加物体");

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");

	DEF_创建物体_Array1D插座_I(u"物理体");
}

C_解算器添加物体节点::~C_解算器添加物体节点() {

}

bool C_解算器添加物体节点::f_update() {
	return false;
}

void C_解算器添加物体节点::f_异步解算() {

}

C_节点基类* f_node_加载解算器添加物体节点(S_设备环境& ctx, FILE* f) {
	C_解算器添加物体节点* node = new C_解算器添加物体节点(ctx);
	return node;
}






C_应用力节点::C_应用力节点(S_设备环境& ctx) : C_节点基类(DEF_应用力节点) {
	m_更新方式 = E_节点更新方式::e_节点更新_实时;
	f_setWName(u"应用力");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建物理体_1D插座_I(u"物理体");
	DEF_创建Vec3_1D插座_I(u"方向");
	DEF_创建Vec3_1D插座_I(u"强度");
	
	DEF_创建物理引擎插座_O(u"物理引擎");


	m_视口互交 = f_alloc_BoolProp(nullptr, u"视口互交");
	m_视口互交.m_私有 = true;
	f_prop_Bool(m_视口互交) = false;

	m_力方式 = f_alloc_EnumProp(nullptr, {
		{u"重力", u""},
		{u"直线", u""},
		{u"关节", u""},
		{u"扭矩", u""},
		{u"控制", u""},
	}, u"力方式");
	m_力方式.m_私有 = true;
}

C_应用力节点::~C_应用力节点() {
	f_prop_Release(m_力方式);
	f_prop_Release(m_视口互交);
}

bool C_应用力节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1));
	auto* 物理体 = DEF_物理体插座_1D数据(f_get输入插座(2));
	auto* 力强度 = DEF_Vec3插座_1D数据(f_get输入插座(3));
	auto* 力坐标 = DEF_Vec3插座_1D数据(f_get输入插座(2));
	

	uint32 num = 物理体->count;
	bool 力强度多例 = 力强度->count >= num;
	bool 力坐标多例 = 力坐标->count >= num;
	
	for (uint32 i = 0; i < num; ++i) {
		S_施加物理力 施加力;
		施加力.force = 力强度多例 ? 力强度->ptr_userData[i] : 力强度->ptr_userData[0];
		施加力.pos = 力坐标多例 ? 力坐标->ptr_userData[i] : 力坐标->ptr_userData[0];

		施加力.bodyID = 物理体->ptr_userData[i]->m_ID;

		f_phy_施加力(m_Physics, 施加力, E_施加力类型(f_prop_enum(m_力方式)) );
	}
	
	f_get输出插座(1)->f_setData(m_Physics);

	return false;
	if (f_prop_Bool(S_节点数据::g_物理引擎视口互交) && S_节点数据::g_当前操作视口相机) {
		
		vec3 ray[2];
		auto mat = f_mat4_左手转右手坐标系(f_mat44_identity());
		ray[0] = mat * S_节点数据::g_视口鼠标点射线[0];
		ray[1] = vec_normalize(S_节点数据::g_视口鼠标点射线[1] - S_节点数据::g_视口鼠标点射线[0]);
		
		float32 dis = 1e+7;
		auto* scene = f_NodeCtx_get默认场景();
		//auto obs = f_scene_射线拾取(scene, mat * S_节点数据::g_视口鼠标点射线[0], mat * S_节点数据::g_视口鼠标点射线[1], &dis);

		//if (obs.size()) {
		//	ray[0] = mat * (S_节点数据::g_视口鼠标点射线[0] + ray[1] * dis);
		//	std::cout << "是否拾取 = " << ray[0].x << " : " << ray[0].y << std::endl;
		//}
		if (S_节点数据::g_施加力.bodyID >= 0) {
			auto 拾取坐标参数 = S_节点数据::g_施加力;
			拾取坐标参数.pos = mat * 拾取坐标参数.pos;
			拾取坐标参数.vec = mat * 拾取坐标参数.vec;
			f_Phy_应用力(m_Physics, S_节点数据::g_施加力);

			std::cout << "移动长度A = " << " x:" << 拾取坐标参数.vec.x << " y:" << 拾取坐标参数.vec.y << " z:" << 拾取坐标参数.vec.z << std::endl;
		}
		
	}

	
	return false;
}

void C_应用力节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_8, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_力方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_应用力节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_力方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建应用力节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_应用力节点(ctx);
}

C_节点基类* f_node_加载应用力节点(S_设备环境& ctx, FILE* f) {
	C_应用力节点* node = new C_应用力节点(ctx);
	return node;
}

void f_node_保存应用力节点(C_节点基类* n, FILE* f) {
	C_应用力节点* node = static_cast<C_应用力节点*>(n);
}





C_PBF更新邻接信息节点::C_PBF更新邻接信息节点(S_设备环境& ctx) : C_节点基类("PBF更新邻接信息节点") {
}

C_PBF更新邻接信息节点::~C_PBF更新邻接信息节点() {
}

bool C_PBF更新邻接信息节点::f_update() {
	return false;
}







C_PBF参数节点::C_PBF参数节点(S_设备环境& ctx) : C_节点基类(DEF_PBF参数) {
	f_setWName(u"PBF参数");

	C_插座基类* socket;
	//1
	DEF_创建物理引擎插座_I(u"物理引擎");

	//2
	DEF_创建F32插座_v1_I(u"时间步进");
	//3
	DEF_创建Vec3插座_v1_I(u"重力");
	//4
	DEF_创建F32插座_v1_I(u"粒子半径");
	//5
	DEF_创建物体插座_I(u"域");
	

	DEF_F32插座数据(f_get输入插座(2)) = 1.0f / 60.0f;
	DEF_Vec3插座数据(f_get输入插座(3)) = { 0.0f, -9.8f,0.0f };
	DEF_F32插座数据(f_get输入插座(4)) = 0.1;
	

	f_phy_initPBF模拟参数(m_流体粒子模拟参数);

	m_迭代次数 = f_alloc_UI32Prop(nullptr, u"迭代次数", 3);
	m_迭代次数.m_私有 = true;

	m_粒子半径 = f_alloc_F32Prop(&m_流体粒子模拟参数.radius, u"粒子半径");
	m_粒子半径.m_私有 = true;
	f_prop_F32(m_粒子半径) = 0.1;

	//13 solidRestDistance
	//DEF_创建F32插座_I(u"固体重置距离");
	m_固体重置距离 = f_alloc_F32Prop(&m_流体粒子模拟参数.solidRestDistance, u"固体重置距离");
	m_固体重置距离.m_私有 = true;
	f_prop_F32(m_固体重置距离) = 0.0;
	
	//14 fluidRestDistance
	//DEF_创建F32插座_I(u"流体重置距离");
	m_流体重置距离 = f_alloc_F32Prop(&m_流体粒子模拟参数.fluidRestDistance, u"流体重置距离");
	m_流体重置距离.m_私有 = true;
	f_prop_F32(m_流体重置距离) = 0.1*0.55;



	//7 maxSpeed
	//DEF_创建F32插座_I(u"最大速度");
	m_最大速度 = f_alloc_F32Prop(&m_流体粒子模拟参数.maxSpeed, u"最大速度");
	m_最大速度.m_私有 = true;
	f_prop_F32(m_最大速度) = 1000.0;
	//7 maxAcceleration
	//DEF_创建F32插座_I(u"最大加速");
	m_最大加速度 = f_alloc_F32Prop(&m_流体粒子模拟参数.maxAcceleration, u"最大加速");
	m_最大加速度.m_私有 = true;
	f_prop_F32(m_最大加速度) = 20;


	//11
	//DEF_创建Vec3插座_I(u"风向");
	m_风向 = f_alloc_Vec3Prop(&m_流体粒子模拟参数.m_Wind, u"风向");
	m_风向.m_私有 = true;
	f_prop_Vec3(m_风向) = { 0,0,0 };
	//11
	//DEF_创建F32插座_I(u"布料拖拽");
	m_布料拖拽 = f_alloc_F32Prop(&m_流体粒子模拟参数.drag, u"布料拖拽");
	m_布料拖拽.m_私有 = true;
	f_prop_F32(m_布料拖拽) = 0.0;
	//12
	//DEF_创建F32插座_I(u"空气阻力");
	m_空气阻力 = f_alloc_F32Prop(nullptr, u"空气阻力");
	m_空气阻力.m_私有 = true;
	f_prop_F32(m_空气阻力) = 0.0;


	
	//4 dynamicFriction
	//DEF_创建F32插座_I(u"动态摩擦");
	m_动态摩擦 = f_alloc_F32Prop(&m_流体粒子模拟参数.dynamicFriction, u"动态摩擦");
	m_动态摩擦.m_私有 = true;
	f_prop_F32(m_动态摩擦) = 0.01;
	//5 staticFriction
	//DEF_创建F32插座_I(u"静态摩擦");
	m_静态摩擦 = f_alloc_F32Prop(&m_流体粒子模拟参数.staticFriction, u"静态摩擦");
	m_静态摩擦.m_私有 = true;
	f_prop_F32(m_静态摩擦) = 0.0;
	//6 particleFriction
	//DEF_创建F32插座_I(u"粒子摩擦");
	m_粒子摩擦 = f_alloc_F32Prop(&m_流体粒子模拟参数.particleFriction, u"粒子摩擦");
	m_粒子摩擦.m_私有 = true;
	f_prop_F32(m_粒子摩擦) = 0.0;
	//6 restitution
	//DEF_创建F32插座_I(u"形态碰撞重置");
	m_碰撞重置 = f_alloc_F32Prop(&m_流体粒子模拟参数.restitution, u"碰撞重置");
	m_碰撞重置.m_私有 = true;
	f_prop_F32(m_碰撞重置) = 0.0;
	//8 adhesion
	//DEF_创建F32插座_I(u"附着力");
	m_附着力 = f_alloc_F32Prop(&m_流体粒子模拟参数.adhesion, u"附着力");
	m_附着力.m_私有 = true;
	f_prop_F32(m_附着力) = 0.0;
	//8 sleepThreshold
	//DEF_创建F32插座_I(u"休眠");
	m_休眠 = f_alloc_F32Prop(&m_流体粒子模拟参数.sleepThreshold, u"休眠");
	m_休眠.m_私有 = true;
	f_prop_F32(m_休眠) = 0.0;
	
	//7 shockPropagation
	//DEF_创建F32插座_I(u"传播收敛");
	m_传播收敛 = f_alloc_F32Prop(&m_流体粒子模拟参数.shockPropagation, u"传播收敛");
	m_传播收敛.m_私有 = true;
	f_prop_F32(m_传播收敛) = 0.0;
	//7 dissipation
	//DEF_创建F32插座_I(u"消散");
	m_消散 = f_alloc_F32Prop(&m_流体粒子模拟参数.dissipation, u"消散");
	m_消散.m_私有 = true;
	f_prop_F32(m_消散) = 0.0;
	//7 damping
	//DEF_创建F32插座_I(u"阻力");
	m_阻力 = f_alloc_F32Prop(&m_流体粒子模拟参数.damping, u"阻力");
	m_阻力.m_私有 = true;
	f_prop_F32(m_阻力) = 0.1;



	//8 cohesion
	//DEF_创建F32插座_I(u"凝聚性");
	m_凝聚性 = f_alloc_F32Prop(&m_流体粒子模拟参数.cohesion, u"凝聚性");
	m_凝聚性.m_私有 = true;
	f_prop_F32(m_凝聚性) = 0.025;
	//8 surfaceTension
	//DEF_创建F32插座_I(u"表面张力");
	m_表面张力 = f_alloc_F32Prop(&m_流体粒子模拟参数.surfaceTension, u"表面张力");
	m_表面张力.m_私有 = true;
	f_prop_F32(m_表面张力) = 0.0;
	//9 viscosity
	//DEF_创建F32插座_I(u"粘度");
	m_粘度 = f_alloc_F32Prop(&m_流体粒子模拟参数.viscosity, u"粘度", 0);
	m_粘度.m_私有 = true;
	//9 vorticityConfinement
	//DEF_创建F32插座_I(u"涡流");
	m_涡流 = f_alloc_F32Prop(&m_流体粒子模拟参数.vorticityConfinement, u"涡流");
	m_涡流.m_私有 = true;
	f_prop_F32(m_涡流) = 30.0;
	//9 anisotropyScale
	//DEF_创建F32插座_I(u"流体球拉伸大小");
	m_流体球拉伸大小 = f_alloc_F32Prop(&m_流体粒子模拟参数.anisotropyScale, u"流体球拉伸大小");
	m_流体球拉伸大小.m_私有 = true;
	f_prop_F32(m_流体球拉伸大小) = 1.0;
	//9 anisotropyMin
	//DEF_创建F32插座_I(u"流体球拉伸最小");
	m_流体球拉伸最小 = f_alloc_F32Prop(&m_流体粒子模拟参数.anisotropyMin, u"流体球拉伸最小");
	m_流体球拉伸最小.m_私有 = true;
	f_prop_F32(m_流体球拉伸最小) = 0.1;
	//9 anisotropyMax
	//DEF_创建F32插座_I(u"流体球拉伸最大");
	m_流体球拉伸最大 = f_alloc_F32Prop(&m_流体粒子模拟参数.anisotropyMax, u"流体球拉伸最大");
	m_流体球拉伸最大.m_私有 = true;
	f_prop_F32(m_流体球拉伸最大) = 2.0;
	//9 smoothing
	//DEF_创建F32插座_I(u"平滑强度");
	m_平滑强度 = f_alloc_F32Prop(&m_流体粒子模拟参数.smoothing, u"平滑强度");
	m_平滑强度.m_私有 = true;
	f_prop_F32(m_平滑强度) = 1.0;
	//9 solidPressure
	//DEF_创建F32插座_I(u"固体压力");
	m_固体压力 = f_alloc_F32Prop(&m_流体粒子模拟参数.solidPressure, u"固体压力");
	m_固体压力.m_私有 = true;
	f_prop_F32(m_固体压力) = 0.0;
	//9 freeSurfaceDrag
	//DEF_创建F32插座_I(u"边界阻力");
	m_边界阻力 = f_alloc_F32Prop(&m_流体粒子模拟参数.freeSurfaceDrag, u"边界阻力");
	m_边界阻力.m_私有 = true;
	f_prop_F32(m_边界阻力) = 0.0;
	//10 buoyancy
	//DEF_创建F32插座_I(u"浮力");
	m_浮力 = f_alloc_F32Prop(&m_流体粒子模拟参数.buoyancy, u"浮力");
	m_浮力.m_私有 = true;
	f_prop_F32(m_浮力) = 1.0;



	//10 diffuseThreshold
	//DEF_创建F32插座_I(u"飞溅产生");
	m_飞溅产生 = f_alloc_F32Prop(&m_流体粒子模拟参数.diffuseThreshold, u"飞溅产生");
	m_飞溅产生.m_私有 = true;
	f_prop_F32(m_飞溅产生) = 100.0;
	//10 diffuseBuoyancy
	//DEF_创建F32插座_I(u"飞溅浮力");
	m_飞溅浮力 = f_alloc_F32Prop(&m_流体粒子模拟参数.diffuseBuoyancy, u"飞溅浮力");
	m_飞溅浮力.m_私有 = true;
	f_prop_F32(m_飞溅浮力) = 1.0;
	//10 diffuseDrag
	//DEF_创建F32插座_I(u"飞溅阻力");
	m_飞溅阻力 = f_alloc_F32Prop(&m_流体粒子模拟参数.diffuseDrag, u"飞溅阻力");
	m_飞溅阻力.m_私有 = true;
	f_prop_F32(m_飞溅阻力) = 0.8;
	//10 diffuseBallistic
	//DEF_创建F32插座_I(u"飞溅发射");
	m_飞溅发射 = f_alloc_I32Prop(&m_流体粒子模拟参数.diffuseBallistic, u"飞溅发射");
	m_飞溅发射.m_私有 = true;
	f_prop_UI32(m_飞溅发射) = 16;
	//10 diffuseLifetime
	//DEF_创建F32插座_I(u"飞溅寿命");
	m_飞溅寿命 = f_alloc_F32Prop(&m_流体粒子模拟参数.diffuseLifetime, u"飞溅寿命");
	m_飞溅寿命.m_私有 = true;
	f_prop_F32(m_飞溅寿命) = 2.0;


	//7 collisionDistance
	//DEF_创建F32插座_I(u"碰撞距离");
	m_碰撞距离 = f_alloc_F32Prop(&m_流体粒子模拟参数.collisionDistance, u"碰撞距离");
	m_碰撞距离.m_私有 = true;
	f_prop_F32(m_碰撞距离) = 0.01;
	//7 particleCollisionMargin
	//DEF_创建F32插座_I(u"碰撞距离边缘");
	m_碰撞距离边缘 = f_alloc_F32Prop(&m_流体粒子模拟参数.particleCollisionMargin, u"碰撞距离边缘");
	m_碰撞距离边缘.m_私有 = true;
	f_prop_F32(m_碰撞距离边缘) = 0.0;
	//7 shapeCollisionMargin
	//DEF_创建F32插座_I(u"碰撞形状边缘");
	m_碰撞形状边缘 = f_alloc_F32Prop(&m_流体粒子模拟参数.shapeCollisionMargin, u"碰撞形状边缘");
	m_碰撞形状边缘.m_私有 = true;
	f_prop_F32(m_碰撞形状边缘) = 0.0;



	m_松弛 = f_alloc_F32Prop(nullptr, u"松弛");
	m_松弛.m_私有 = true;
	f_prop_F32(m_松弛) = 1.0;
	m_松弛模式 = f_alloc_EnumProp(nullptr, { {u"全局", u""}, {u"局部", u""} }, u"松弛方式");
	m_松弛模式.m_私有 = true;
	f_prop_enum(m_松弛模式) = 1;
	
	
	


	DEF_创建物理引擎插座_O(u"物理引擎");



}

C_PBF参数节点::~C_PBF参数节点()
{
}

bool C_PBF参数节点::f_update() {
	S_Physics* m_Physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	if (!m_Physics) {
		f_get输出插座(1)->f_setData((void*)nullptr);
		return false;
	}

	f_phy_set模拟参数(m_Physics, m_流体粒子模拟参数);
	
	f_get输出插座(1)->f_setData(m_Physics);
	return false;
}

void C_PBF参数节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_迭代次数, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子半径, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_固体重置距离, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_流体重置距离, 下一次读取数据指针);

		下一次读取数据指针 = f_prop_Load(m_最大加速度, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_最大速度, 下一次读取数据指针);


		下一次读取数据指针 = f_prop_Load(m_风向, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_布料拖拽, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_空气阻力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_动态摩擦, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_静态摩擦, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粒子摩擦, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_碰撞重置, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_附着力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_休眠, 下一次读取数据指针);
		
		下一次读取数据指针 = f_prop_Load(m_传播收敛, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_消散, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_阻力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_凝聚性, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_表面张力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_粘度, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_涡流, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_流体球拉伸大小, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_流体球拉伸最小, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_流体球拉伸最大, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_平滑强度, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_固体压力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_边界阻力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_浮力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_飞溅产生, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_飞溅浮力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_飞溅阻力, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_飞溅发射, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_飞溅寿命, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_碰撞距离, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_碰撞距离边缘, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_碰撞形状边缘, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_松弛, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_松弛模式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_PBF参数节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_迭代次数, 块);
	f_prop_Save(m_粒子半径, 块);
	f_prop_Save(m_固体重置距离, 块);
	f_prop_Save(m_流体重置距离, 块);

	f_prop_Save(m_最大加速度, 块);
	f_prop_Save(m_最大速度, 块);
	

	f_prop_Save(m_风向, 块);
	f_prop_Save(m_布料拖拽, 块);
	f_prop_Save(m_空气阻力, 块);
	f_prop_Save(m_动态摩擦, 块);
	f_prop_Save(m_静态摩擦, 块);
	f_prop_Save(m_粒子摩擦, 块);
	f_prop_Save(m_碰撞重置, 块);
	f_prop_Save(m_附着力, 块);
	f_prop_Save(m_休眠, 块);
	
	f_prop_Save(m_传播收敛, 块);
	f_prop_Save(m_消散, 块);
	f_prop_Save(m_阻力, 块);
	f_prop_Save(m_凝聚性, 块);
	f_prop_Save(m_表面张力, 块);
	f_prop_Save(m_粘度, 块);
	f_prop_Save(m_涡流, 块);
	f_prop_Save(m_流体球拉伸大小, 块);
	f_prop_Save(m_流体球拉伸最小, 块);
	f_prop_Save(m_流体球拉伸最大, 块);
	f_prop_Save(m_平滑强度, 块);
	f_prop_Save(m_固体压力, 块);
	f_prop_Save(m_边界阻力, 块);
	f_prop_Save(m_浮力, 块);
	f_prop_Save(m_飞溅产生, 块);
	f_prop_Save(m_飞溅浮力, 块);
	f_prop_Save(m_飞溅阻力, 块);
	f_prop_Save(m_飞溅发射, 块);
	f_prop_Save(m_飞溅寿命, 块);
	f_prop_Save(m_碰撞距离, 块);
	f_prop_Save(m_碰撞距离边缘, 块);
	f_prop_Save(m_碰撞形状边缘, 块);
	f_prop_Save(m_松弛, 块);
	f_prop_Save(m_松弛模式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建PBF参数节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_PBF参数节点(ctx);
}

C_节点基类* f_node_加载PBF参数节点(S_设备环境& ctx, FILE* f) {
	C_PBF参数节点* node = new C_PBF参数节点(ctx);
	return node;
}

void f_node_保存PBF参数节点(C_节点基类* n, FILE* f) {
	C_PBF参数节点* node = static_cast<C_PBF参数节点*>(n);
}




C_更新肌腱节点::C_更新肌腱节点(S_设备环境& ctx) : C_节点基类(DEF_更新肌腱节点) {
	f_setWName(u"FleX参数");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物理引擎插座_I(u"物理引擎");
	DEF_创建I32插座_I(u"ID", nullptr);
	DEF_创建F32插座_I(u"强度", nullptr);
	
	DEF_创建物理引擎插座_O(u"物理引擎");
	
}

C_更新肌腱节点::~C_更新肌腱节点() {
}

bool C_更新肌腱节点::f_update() {
	auto* physics = DEF_物理引擎插座数据(f_get输入插座(1), 0);
	
	if (physics) {
		auto& ID = DEF_I32插座数据(f_get输入插座(2));
		auto& 强度 = DEF_F32插座数据(f_get输入插座(3), 0);

		f_phy_set肌腱力度(physics, &强度, ID);
	}
	
	f_get输出插座(1)->f_setData(physics);
	return false;
}

void C_更新肌腱节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
}

void C_更新肌腱节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
}

C_节点基类* f_node_加载更新肌腱节点(S_设备环境& ctx, FILE* f) {
	C_更新肌腱节点* node = new C_更新肌腱节点(ctx);
	return node;
}

void f_node_保存更新肌腱节点(C_节点基类* n, FILE* f) {
	C_更新肌腱节点* node = dynamic_cast<C_更新肌腱节点*>(n);
}




